package com.speedchina.permission.service.sys.impl;

import com.speedchina.framework.base.TService;
import com.speedchina.framework.helper.Assert;
import com.speedchina.permission.base.sysenum.ResourceEnum;
import com.speedchina.permission.dao.sys.ResourceDao;
import com.speedchina.permission.domain.sys.dto.ResourceDTO;
import com.speedchina.permission.domain.sys.entity.Resource;
import com.speedchina.permission.domain.sys.entity.Role;
import com.speedchina.permission.domain.sys.entity.User;
import com.speedchina.permission.domain.sys.po.ResourcePo;
import com.speedchina.permission.service.sys.ResourceService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 *  服务层实现类
 * @author winter
 * @date 2021-04-07 15:19:42
 */
@Service
public class ResourceServiceImpl extends TService<ResourceDao, Resource> implements ResourceService {
    @Override
    public List<ResourceDTO> trees(ResourcePo params) {
        List<ResourceDTO> list = baseMapper.queryList(params);
        return buildResourceTrees(list);
    }

    /**
     * 查询用户所有菜单列表
     * 1.包含用户的角色菜单和用户独立菜单权限
     * @param user
     * @return
     */
    @Override
    public List<ResourceDTO> queryUserMenu(User user) {
        return baseMapper.queryUserMenu(user);
    }

    /**
     * 查询用户所有菜单树
     * 1.包含用户的角色菜单和用户独立菜单权限
     * @param user
     * @return
     */
    @Override
    public List<ResourceDTO> queryUserMenuTree(User user) {
        List<ResourceDTO> listNotParent = baseMapper.queryUserMenuList(user.getId(),"");
        List<ResourceDTO> allRes = baseMapper.queryList(new ResourcePo());
        List<ResourceDTO> list = findResourceParent(allRes,listNotParent);
        list.addAll(listNotParent);
        list = uniqueList(list);
        return buildResourceTrees(list);
    }

    @Override
    public Set<String> getPermissions(String id) {
        return baseMapper.getUserPermissionsById(id);
    }

    /**
     * 资源列表去重
     * @param resources
     * @return
     */
    public List<ResourceDTO> uniqueList(List<ResourceDTO> resources){
        List<ResourceDTO> list = new ArrayList<>();
        Set<String> set = new HashSet<>();
        for (ResourceDTO resourceDTO:resources){
            if(!"2".equals(resourceDTO.getType())&&!set.contains(resourceDTO.getId())){
                list.add(resourceDTO);
                set.add(resourceDTO.getId());
            }
        }
        return list;
    }
    /**
     * 级联删除
     * 1.先查找ids中为父节点的id，从父节点向下搜索子节点作为删除的节点
     * @param ids
     * @return
     */
    @Override
    @Transactional(rollbackFor=Exception.class)
    public boolean deleteLinkedBatch(List<Serializable> ids) {
        List<ResourceDTO> allRes = baseMapper.queryList(new ResourcePo());
        List<ResourceDTO> list = new ArrayList<>();
        for (Serializable id:ids){
            List<ResourceDTO> childrenList = findChildrenList(allRes, new ResourceDTO(id.toString()));
            list.add(new ResourceDTO(id.toString()));
            list.addAll(childrenList);
        }
        Set<String> delIds = new HashSet<>();
        for (ResourceDTO resourceDTO:list){
            delIds.add(resourceDTO.getId());
        }
        for (String id:delIds){
            resourceIsUse(id);
        }
        baseMapper.deleteBatchIds(delIds);
        return true;
    }

    /**
     * 构建资源tree
     * @param treeNodes
     * @return
     */
    private List<ResourceDTO> buildResourceTrees(List<ResourceDTO> treeNodes){
        List<ResourceDTO> trees = new ArrayList<>();
        for (ResourceDTO treeNode : treeNodes) {
            //无插叙条件的情况建立树
            if(isParent(treeNodes,treeNode)){
                ResourceDTO tree = findChildren(treeNodes, treeNode);
                if(tree.getChildren()!=null&&tree.getChildren().isEmpty()){
                    tree.setChildren(null);
                }
                trees.add(tree);
            }
        }
        return trees;
    }

    /**
     * 查找 资源缺少的父节点
     * @param allRes
     * @param listNotParent
     * @return
     */
    private List<ResourceDTO> findResourceParent(List<ResourceDTO> allRes,List<ResourceDTO> listNotParent){
        List<ResourceDTO> list = new ArrayList<>();
        for(ResourceDTO resourceDTO:listNotParent){
            //若当前节点是最顶层节点且parentId不为0，那么认为此节点是缺少父级的，因此需要查找他的所有上级并添加进来
            if(isParent(listNotParent,resourceDTO) && !"0".equals(resourceDTO.getParentId())){
                List<ResourceDTO> parents = findParent(allRes,resourceDTO);
                list.addAll(parents);
            }
        }
        return list;
    }

    /**
     * 查找父节点 (list平行结构)
     * @param allRes
     * @param resourceDTO
     * @return
     */
    private List<ResourceDTO> findParent(List<ResourceDTO> allRes, ResourceDTO resourceDTO) {
        List<ResourceDTO> list = new ArrayList<>();
        for(ResourceDTO everyNode:allRes){
            if(everyNode.getId().equals(resourceDTO.getParentId())){
                list.add(everyNode);
                if(!"0".equals(everyNode.getParentId())){
                    findParent(allRes,everyNode);
                }
            }
        }
        return list;
    }

    private List<ResourceDTO> findChildrenList(List<ResourceDTO> treeNodes, ResourceDTO resourceDTO){
        List<ResourceDTO> list = new ArrayList<>();
        for(ResourceDTO everyNode:treeNodes) {
            if (everyNode.getParentId().equals(resourceDTO.getId())) {
                list.add(everyNode);
                findChildrenList(treeNodes,everyNode);
            }
        }
        return list;
    }
    /**
     * 查找子节点 ， 树形结构
     * @param treeNodes
     * @param resourceDTO
     * @return
     */
    private ResourceDTO findChildren(List<ResourceDTO> treeNodes, ResourceDTO resourceDTO){
        for(ResourceDTO everyNode:treeNodes){
            if(resourceDTO.getId().equals(everyNode.getParentId())){
                ResourceDTO node = findChildren(treeNodes,everyNode);
                if(null != node){
                    if (resourceDTO.getChildren()==null||resourceDTO.getChildren().isEmpty()){
                        resourceDTO.setChildren(new ArrayList<ResourceDTO>());
                    }
                    resourceDTO.getChildren().add(node);
                }
            }
        }
        return resourceDTO;
    }

    /**
     * 是否是根节点，找不到根节点就是根节点
     * @param treeNodes
     * @param resourceDTO
     * @return
     */
    private boolean isParent(List<ResourceDTO> treeNodes, ResourceDTO resourceDTO){
        for(ResourceDTO node: treeNodes){
            if(node.getId().equals(resourceDTO.getParentId())){
                return false;
            }
        }
        return true;
    }
    private void resourceIsUse(Serializable id){
        List<Role> roles =baseMapper.getResourceRole(id);
        StringBuffer sb = new StringBuffer();
        System.err.println(roles);
        for (Role role:roles){
            sb.append(role.getName()+"、");
        }
        if(sb.length()>1){
            sb.deleteCharAt(sb.length() - 1);
        }
        Assert.isTrue(!roles.isEmpty(),sb.toString()+ ResourceEnum.ROLE_IS_USE_BY_ROLE.getMsg());
        List<User> users = baseMapper.getResourceUser(id);
        StringBuffer stringBuffer = new StringBuffer();
        for (User user:users){
            stringBuffer.append(user.getUsername()+"、");
        }
        if(stringBuffer.length()>1){
            stringBuffer.deleteCharAt(stringBuffer.length() - 1);
        }
        Assert.isTrue(!users.isEmpty(),stringBuffer.toString()+ ResourceEnum.ROLE_IS_USE_BY_USER.getMsg());
    }
}